# -*- coding: utf-8 -*
import re
from Enums import FileType
from PrintTool import PrintTool
from SingleFileInfo import SingleFileInfo


# 文件解析类
class FileParser:

    # 根据字符串解析并返回相应信息
    def parse_file_info(self, fo, file_type: FileType):
        if file_type is FileType.C:
            return self.__parse_c_file_info(fo)
        elif file_type is FileType.Ruby:
            return self.__parse_ruby_file_info(fo)

    # ruby类文件解析方法
    def __parse_ruby_file_info(self, fo):
        self.__reset_data()
        comment_block_flag = False  # /*注释标识, 用于标记当前检察代码是否还在代码块中
        f_lines = fo.readlines()
        for line_str in f_lines:
            self.line_type_list.add_line()
            l_strip = line_str.strip()  # 经过去空格之后的行信息
            debug_str = ('{1}'.format(self.line_type_list.line, l_strip))  # debug信息

            if l_strip == '':
                self.line_type_list.add_blank()
                continue
            if comment_block_flag:  # 如果当前行在注释块中
                if re.match('^=end', l_strip) is not None:  # 以 =end 开头的, 表示注释块的结束
                    comment_block_flag = False
                self.line_type_list.add_comment(debug_str)
            else:
                if re.match('^=begin', l_strip) is not None:  # 以 =begin 开头的, 表示注释块的结束
                    comment_block_flag = True
                    self.line_type_list.add_comment(debug_str)
                    continue
                elif re.match('^#', l_strip) is not None:  # 以#开头的注释
                    self.line_type_list.add_comment(debug_str)
                else:
                    self.line_type_list.add_code(debug_str)
        return self.line_type_list

    def __init__(self):
        self.__reset_data()

    # 重置数据
    def __reset_data(self):
        self.line_type_list = SingleFileInfo()  # 行信息统计
        self.line_symbol_stack = []  # 符号栈, 用于存储成对符号

    # c类文件的解析方法
    def __parse_c_file_info(self, fo):
        self.__reset_data()
        f_lines = fo.readlines()
        for line_str in f_lines:
            self.line_type_list.add_line()
            strip_line = line_str.strip()  # 前后去空格的一行信息
            debug_str = ('{0} {1}'.format(self.line_type_list.line, strip_line))  # debug信息
            # 先判断是否为空行, 如果是空行就直接保存信息, 并continue
            if strip_line == '':
                self.line_type_list.add_blank()
                continue

            # 判断是否在char中
            if self.__get_line_symbol_top() == 'char':
                self.line_type_list.add_code(debug_str)
            else:
                # 判断是否在/* */中
                if self.__get_line_symbol_top() != '/*':
                    if self.re_match('^//', strip_line) or self.re_match('^/\*', strip_line):
                        self.line_type_list.add_comment(debug_str)
                    else:
                        self.line_type_list.add_code(debug_str)
                else:
                    # 检察是否是是含有注释的code行
                    if self.re_match('^[^\*/]*\*/.+', strip_line):
                        self.line_type_list.add_code(debug_str)
                    else:
                        self.line_type_list.add_comment(debug_str)
            self.__update_type_stack_by_line(strip_line)
        return self.line_type_list

    # 根据相应代码行, 更新stack
    def __update_type_stack_by_line(self, line):
        # 检察char类型
        if self.__get_line_symbol_top() == 'char':
            if FileParser.re_match('\)\"[;]*$', line):  # 如果是char结尾行
                self.line_symbol_stack.pop()
            return
        # 如果是char开头, 并且没有""成对出现, 则标记
        if self.re_match('^char[ ]*\*[^"]*"[^"]*$', line):
            self.line_symbol_stack.append('char')
            return
        if self.__get_line_symbol_top() != '/*':
            # 如果包含/*并不包含*/的, 则进行标记
            if self.re_match('^[^"]*/\*((?!\*/).)*$', line):
                self.line_symbol_stack.append('/*')
        else:
            # 如果是以*/结尾的, 则弹出标记
            if self.re_match('^[^\*/]*\*/', line):
                self.line_symbol_stack.pop()

    # 返回类型历史栈栈顶元素
    def __get_line_symbol_top(self):
        if len(self.line_symbol_stack) > 0:
            return self.line_symbol_stack[len(self.line_symbol_stack) - 1]
        return ""

    # 是否符合相应正则(封装)
    @staticmethod
    def re_match(pattern, string, flags=0):
        return re.match(pattern, string, flags) is not None
